package api

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/olivere/elastic/v7"
	"go.uber.org/zap"
	"go_es/server/global"
	"go_es/server/model"
	"go_es/server/model/common/response"
	systemReq "go_es/server/model/request"
	"go_es/server/service"
	"go_es/server/utils"
	"gorm.io/gorm"
	"reflect"
)

type WeiboApi struct{}

func (w *WeiboApi) GetWeiboIndex(c *gin.Context) {
	var req systemReq.WeiboIndex
	err := c.ShouldBind(&req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = utils.Verify(req, utils.WeiBoIndexVerify)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()

	// 首先检测下weibo索引是否存在
	exists, err := global.GVA_ES.IndexExists(req.Index).Do(ctx)
	if err != nil {
		// Handle error
		response.FailWithMessage(err.Error(), c)
		return
	}
	if !exists {
		// weibo索引不存在，则创建一个
		_, err := global.GVA_ES.CreateIndex(req.Index).BodyString(model.Mapping).Do(ctx)
		if err != nil {
			// Handle error
			response.FailWithMessage(err.Error(), c)
			return
		}
	}

	// 根据id查询文档
	get1, err := global.GVA_ES.Get().
		Index(req.Index). // 指定索引名
		Id("1"). // 设置文档id
		Do(ctx) // 执行请求
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	if get1.Found {
		msg2 := model.Weibo{}
		data, _ := get1.Source.MarshalJSON()
		err = json.Unmarshal(data, &msg2)
		if err != nil {
			response.FailWithMessage("解析es中获取的数据失败", c)
			return
		}
		response.OkWithData(msg2, c)
	} else {
		response.FailWithMessage("没有数据", c)
	}
}

func (w *WeiboApi) AddWeibo(c *gin.Context) {

	type AddRequest struct {
		Field string `bind:"required" json:"field" form:"field"`
		Index string `bind:"required" json:"index" form:"index"`
	}
	var req AddRequest
	err := c.ShouldBind(&req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	var authAdmins []model.AuthAdmin
	err = json.Unmarshal([]byte(req.Field), &authAdmins)
	if err != nil {
		response.FailWithMessage("数据解析失败", c)
		return
	}
	//2.校验数据 使用redis去重
	var insertAdmins []model.AuthAdmin
	for _, user := range authAdmins {
		isExist, _:= global.GVA_REDIS.SIsMember(context.Background(), req.Index, *user.Mobile).Result()
		if isExist{
			continue //数据已经添加过
		}
		insertAdmins = append(insertAdmins, user)
		_, err = global.GVA_REDIS.SAdd(context.Background(), req.Index, *user.Mobile).Result()
		if err != nil {
			global.GVA_LOG.Error("集合中添加数据失败", zap.String("auth_admin", err.Error()))
		}
	}

	if len(insertAdmins) > 0 {
		rabbit := service.NewRabbitMQ("go_es", "auth_admin", "auth_admin_queue")
		global.GVA_DB.Transaction(func(tx *gorm.DB) error {
			if err := tx.Model(&model.AuthAdmin{}).Save(insertAdmins).Error; err != nil {
				return err
			}
			//3.同步到消息队列rabbitMQ
			message, _ := json.Marshal(insertAdmins)
			if err := rabbit.SendMessage(service.Message{Body: string(message)}); err != nil {
				return err
			}
			return nil
		})
		defer rabbit.Close()
	}
	response.Ok(c)
	return
}


func (w *WeiboApi) SearchWeibo(c *gin.Context)  {
	var req systemReq.SearchWeibo
	err := c.ShouldBind(&req)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	err = utils.Verify(req, utils.SearchWeiboVerify)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	contentType := utils.IdentifyInputType(req.Content)
	if contentType == "unknown" {
		response.FailWithMessage("请输入姓名、手机号、身份证号中的任意一个", c)
		return
	}
	var authAdmins []model.AuthAdmin
	// 执行ES请求需要提供一个上下文对象
	ctx := context.Background()
	termQuery := elastic.NewTermQuery("", "")
	switch contentType {
	case "name":
		termQuery = elastic.NewTermQuery("realname", req.Content)
		break
	case "phone":
		termQuery = elastic.NewTermQuery("mobile", req.Content)
		break
	case "IDCard":
		termQuery = elastic.NewTermQuery("id", req.Content)
	}
	searchResult, err := global.GVA_ES.Search().
		Index("auth_admin").
		Query(termQuery).
		From(0).Size(10).
		Pretty(true).
		Do(ctx)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	for _, item := range searchResult.Each(reflect.TypeOf(model.AuthAdmin{})) {
		t := item.(model.AuthAdmin)
		fmt.Printf("authAdmin by %s: %s\n", t.Realname, *t.Mobile)
		authAdmins = append(authAdmins, t)
	}
	response.OkWithData(authAdmins, c)
	return
}